package net.ermannofranco.xmltest;

import static net.ermannofranco.xml.schema.Facet.ENUMERATION;
import static net.ermannofranco.xml.schema.Facet.WHITESPACE;
import static net.ermannofranco.xml.schema.Facet.Whitespace.PRESERVE;
import static net.ermannofranco.xml.schema.Use.REQUIRED;
import static net.ermannofranco.xml.schema.XmlType.DECIMAL;
import static net.ermannofranco.xml.schema.XmlType.POS_INTEGER;
import static net.ermannofranco.xml.schema.XmlType.STRING;
import junit.framework.Assert;
import net.ermannofranco.xml.Indent;
import net.ermannofranco.xml.Namespace;
import net.ermannofranco.xml.schema.Attribute;
import net.ermannofranco.xml.schema.Choice;
import net.ermannofranco.xml.schema.ComplexType;
import net.ermannofranco.xml.schema.Element;
import net.ermannofranco.xml.schema.Facet;
import net.ermannofranco.xml.schema.Schema;
import net.ermannofranco.xml.schema.Sequence;
import net.ermannofranco.xml.schema.SimpleType;
import net.ermannofranco.xml.schema.XmlType;
import net.ermannofranco.xml.schema.validation.XsdValidator;

import org.junit.Test;

//http://www.w3schools.com/schema/schema_example.asp
public class ProvaW3School {

	private final Schema sMonolithic;
	private final Schema sDivided;
	private final Schema s3;
	private final Schema s4;

	public ProvaW3School()  {

		Namespace target = new Namespace("www3", "prova.w3c");
		sMonolithic = new Schema(getClass()).setTargetNamespace(target);

		ComplexType ct1 = sMonolithic.addElem("shiporder").setComplexType();

		Sequence seq1 = ct1.setSequence();
		seq1.addElem("orderperson").setType(STRING);

		Sequence seq2 = seq1.addElem("shipto").setComplexType().setSequence();
		seq2.addElem("name").setType(STRING);
		seq2.addElem("address").setType(STRING);
		seq2.addElem("city").setType(STRING);
		seq2.addElem("country").setType(STRING);

		Sequence seq3 = seq1.addElem("item").setUnboundedMaxOccurs()
				.setComplexType().setSequence();
		seq3.addElem("title").setType(STRING);
		seq3.addElem("note").setType(STRING).setZeroMinOccurs();
		seq3.addElem("quantity").setType(POS_INTEGER);
		seq3.addElem("price").setType(DECIMAL);

		ct1.addTagAttribute("orderid", STRING, REQUIRED);
		// *********************************************************************************//

		sDivided = new Schema(getClass()).setTargetNamespace(target);

		// <!-- definition of simple elements -->
		Element orderpersonEl = sDivided.addElem("orderperson").setType(STRING);
		Element nameEl = sDivided.addElem("name").setType(STRING);
		Element addressEl = sDivided.addElem("address").setType(STRING);
		Element cityEl = sDivided.addElem("city").setType(STRING);
		Element countryEl = sDivided.addElem("country").setType(STRING);
		Element titleEl = sDivided.addElem("title").setType(STRING);
		Element noteEl = sDivided.addElem("note").setType(STRING);
		Element quantityEl = sDivided.addElem("quantity").setType(POS_INTEGER);
		Element priceEl = sDivided.addElem("price").setType(DECIMAL);

		// <!-- definition of attributes -->
		Attribute orderid = sDivided.addTagAttribute("orderid", STRING);

		// <!-- definition of complex elements -->
		Element shiptoEl = sDivided.addElem("shipto");
		Sequence seqDiv1 = shiptoEl.setComplexType().setSequence();
		seqDiv1.addElem(nameEl);
		seqDiv1.addElem(addressEl);
		seqDiv1.addElem(cityEl);
		seqDiv1.addElem(countryEl);

		Element itemEl = sDivided.addElem("item");
		Sequence seqDiv2 = itemEl.setComplexType().setSequence();
		seqDiv2.addElem(titleEl);
		seqDiv2.addElem(noteEl).setZeroMinOccurs();
		seqDiv2.addElem(quantityEl);
		seqDiv2.addElem(priceEl);

		ComplexType cDiv1 = sDivided.addElem("shiporder").setComplexType();
		Sequence seqDiv3 = cDiv1.setSequence();
		seqDiv3.addElem(orderpersonEl);
		seqDiv3.addElem(shiptoEl).setZeroMinOccurs();
		seqDiv3.addElem(itemEl).setUnboundedMaxOccurs();
		seqDiv3.addElem(priceEl);
		cDiv1.addTagAttribute(orderid, REQUIRED);
		// *********************************************************************************//
		SimpleType inttype, dectype;
		ComplexType shiptotype, itemtype, shipordertype;
		s3 = new Schema(getClass()).setTargetNamespace(target);

		SimpleType stringtype0 = s3.addSimpleType("stringtype0");
		stringtype0.setRestriction().setSimpleType().setList().setItemType(
				XmlType.INT);
		SimpleType stringtype1 = s3.addSimpleType("stringtype1");
		stringtype1.setList().setSimpleType().setRestriction(XmlType.BOOLEAN);
		SimpleType stringtype2 = s3.addSimpleType("stringtype2");
		stringtype2.setRestriction().setSimpleType().setUnion().setMemberTypes(
				stringtype1, stringtype0);

		(inttype = s3.addSimpleType("inttype")).setRestriction(POS_INTEGER);
		(dectype = s3.addSimpleType("dectype")).setRestriction(DECIMAL);
		s3.addSimpleType("orderidtype").setRestriction(STRING, Facet.PATTERN,
				"[0-9]{6}");
		Sequence seq4 = (shiptotype = s3.addComplexType("shiptotype"))
				.setSequence();
		seq4.addElem("name", stringtype0);
		seq4.addElem("address", stringtype1);
		seq4.addElem("city", stringtype0);
		seq4.addElem("country", stringtype2);

		Sequence seq5 = (itemtype = s3.addComplexType("itemtype"))
				.setSequence();
		seq5.addElem("title", stringtype0);
		seq5.addElem("note", stringtype1).setZeroMinOccurs();
		seq5.addElem("quantity", inttype);
		seq5.addElem("price", dectype);

		shipordertype = s3.addComplexType("shipordertype");
		Sequence seq6 = shipordertype.setSequence();
		seq6.addElem("orderperson", "stringtype0");
		seq6.addElem("shipto", shiptotype);
		seq6.addElem("item", itemtype).setUnboundedMaxOccurs();
		shipordertype.addTagAttribute("orderid", "orderidtype", REQUIRED);

		s3.addElem("shiporder", shipordertype);

		// ***************************************************************//
		SimpleType carType;
		s4 = new Schema(getClass()).setTargetNamespace(target);

		(carType = s4.addSimpleType("carType")).setRestriction(STRING)
				.addFacet(ENUMERATION, "Audi").addFacet(ENUMERATION, "Golf")
				.addFacet(ENUMERATION, "BMW");
		Element car = s4.addElem("car", carType);
		Element address = s4.addElem("address");
		address.setSimpleType().setRestriction(STRING).addFacet(
				WHITESPACE, PRESERVE);
		Choice choice = s4.addElem("root").setComplexType().setChoice();
		choice.addElem(car);
		choice.addElem(address);
	}

	public static void main(String[] args)  throws Exception {
		ProvaW3School prova = new ProvaW3School();
		prova.sMonolithic.save("sMonolithic", Indent.LARGE).print();
		prova.sDivided.save("sDivided").print();
		prova.s3.save("s3").print();
		prova.s4.save("s4").print();
	}

	@Test
	public void mainTest() throws Exception {
		ProvaW3School multiSchema = new ProvaW3School();
		multiSchema.sMonolithic.logInfo(Indent.SMALL).save("sMonolithic", Indent.SMALL);
		Assert.assertEquals(0, sMonolithic.getErrors());
		
		multiSchema.sDivided.logInfo(Indent.MEDIUM).save("sDivided", Indent.SMALL);
		Assert.assertEquals(0, sDivided.getErrors());
		
		multiSchema.s3.logInfo(Indent.MEDIUM).save("s3", Indent.SMALL);
		Assert.assertEquals(0, s3.getErrors());
		
		multiSchema.s4.logInfo(Indent.SMALL).save("s4", Indent.SMALL);
		Assert.assertEquals(0, s4.getErrors());

	}
}